Prise en main de l'IDE Pyzo et du language Python

Table des matières

Première connexion et configuration

Connexion à l'ordinateur

  • Allumer l'ordinateur.
  • Se connecter.
    • votre identifiant est de la forme prenom.nom sans accents et éventuellement tronqués au premier sous mot (avant tout - ou espace).
    • votre mot de passe est votre date de naissance, sous la forme jjmmaaaa.

Configuration de Pyzo

Pyzo est un IDE (Integrated Development Environment : un logiciel qui regroupe plusieurs outils utiles au développement) pour la programmation en Python. C'est un logiciel libre.

  1. Lancer l'application Pyzo

    pyzo_logo.png

  2. Pyzo détecte automatiquement un environnement Python préinstallé. Si nécessaire, cliquer sur le lien pour confirmer l'utilisation de cet environnement.

Le logiciel Pyzo présente plusieurs fenêtres. On n'utilisera que les deux fenêtres suivantes — fermer les autres.

  • L'éditeur de texte interactif
  • Le shell, ou invite de commande. Sa fenêtre ressemble à la fenêtre de droite de la capture suivante. Selon la configuration, l'invite In [1]: du shell IPython peut être remplacée l'invite $\inv$ du shell de base.

Pyzo - editeur - invite.png

  1. (optionnel, utile pour cette séance) Configurer l'utilisation de IPython :
    • Dans le menu Shell, choisir Configuration des shells
    • Cocher Utilise IPython si disponible, puis Done.
    • Menu Shell > Redémarrer.

1. Le shell

L'invite In [1]: (ou $\inv$ selon les versions) vous invite à entrer une commande, ou plutôt une expression dans le langage Python. Le shell va alors l'exécuter, et vous donner le résultat. Accepter l'invitation en écrivant une expression arithmétique comme 1+1, et appuyer sur la touche entrée.

Comme expliqué dans le message de bienvenue, en plus d'évaluer des expressions dans le langage Python, le shell

  • permet d'accéder à de la documentation, ou des détails sur des objets Python, via help, ou help(objet).
  • accepte des commandes «magiques». Par exemple, la commande %time (ou timeit) permet de mesurer le temps d'exécution de code Python.

1.1. Premiers types et opérateurs

Les objets manipulés ont un type, dont voici les plus élémentaires, et ce qu'ils représentent.

type Python représente exemples de valeurs
int (integer) un nombre entier relatif 1, -3
float (floating-point) un nombre à virgule, appelé un flottant 1.133
str (string) du texte, appelé chaîne de caractères "Jean Jaurès"
bool (boolean) Vrai/Faux, appelé booléen True, False

Autre type fondamental : les listes, comme [3, 2, 6, 4], qui représentent un tableau de valeurs.

Les fonctions type et isinstance permettre de connaître le type d'un objet.

  • type(1.13) renvoie <class 'float'>.
  • isinstance(x, int) teste si la variable x représente un entier.

Les opérateurs arithmétiques de base +, -, *, / sont définis en Python. On peut utiliser le shell comme une calculatrice.

Quel est le type de l'expression 10 / 2 ?

Il faut être attentif au type d'un objet, car un même opérateur peut avoir des sens différents selon le type auquel il s'applique.

À l'aide du shell, déterminer ce que renvoient les expressions suivantes et leur type.

  1. 3 + 5
  2. 3 + 5.0
  3. "bon" + "jour"
  4. True + False

1.2. Variables et affectation

Les variables en Python ne sont pas comme des variables en mathématiques, qui peuvent prendre n'importe quelle valeur. Une variable Python n'existe que lorsqu'elle a été définie en y mettant une valeur particulière, ce qu'on appelle l'affectation. Une variable Python est comme une case mémoire.

In [1]: a = 3 # Définition d'une variable a
              # le shell ne renvoit rien
In [2]: a * 2 # On utilise la variable
Out[2]: 6
In [3]: b = a+2

In [4]: a = a*a

In [5]: a
Out[5]: 9
In [6]: a+b
Out[6]: 14

Les instructions précédentes définissent une variable a, et lui affectent initialement la valeur $3$. Cette variable peut être utilisée dans les expressions suivantes, elle y est remplacée par sa valeur. L'instruction a=a*a réaffecte la valeur $9$ à la variable a.

Noter que les affectations ne renvoient rien : il n'y a pas de résultat (pas de Out).

Les noms de variables sont des séquences de lettres ou de chiffres, commençant toujours par une lettre, sans caractères spéciaux (hormis l'underscore $\underline{\,\,\,\,}$) et sensibles à la casse (majuscule vs minuscule).

Compléter le tableau suivant :

Instruction type de a type de b valeur dans la variable a valeur dans la variable b
a = 5 * 9   \cellcolor{gray!50}   \cellcolor{gray!50}
b = a / 2 \cellcolor{gray!50}   \cellcolor{gray!50}  
a = int(b)   \cellcolor{gray!50}   \cellcolor{gray!50}
a = b - 4*a   \cellcolor{gray!50}   \cellcolor{gray!50}
a = "b" + "a"   \cellcolor{gray!50}   \cellcolor{gray!50}

1.3. Les entiers

Les entiers relatifs sont représentés en Python par le type int (pour integer). Contrairement à d'autres langages de programmation, le type int de Python permet de représenter des entiers arbitrairement grands.

En plus des opérations +,-,*, Python définit les opérateurs suivants.

a % b le reste de la division euclidienne de a par b.
a // b le quotient de la division euclidienne de a par b.
a ** b a puissance b.
In [1]: 42 % 10
Out[1]: 2
In [2]: 42 // 10
Out[2]: 4
In [3]: 3 ** 3
Out[3]: 27

L'opérateur de division / renvoie un flottant (un nombre à virgule), même si la division est entière : 6 / 2 renvoie 3.0. Pour obtenir l'entier 3, il faut utiliser 6 // 2.

Cela peut être source d'erreurs : d'une part certaines fonctions demandent des arguments entiers (comme range pour une itération), d'autre part les opérations d'arithmétique sur les flottants ne sont pas toujours exactes.

L'opérateur de puissance ** renvoie un flottant si l'exposant est négatif. Il fonctionne aussi avec des arguments flottants : 1.2 ** 2.3 renvoie 1.5209…

Ne pas utiliser $a^\wedge b$ pour calculer $a^b$. Manque de chance, cet opérateur existe donc le code s'exécutera sans erreurs, mais au lieu de calculer $a^b$, il réalise un XOR bit par bit.

On considère la suite $(u_n)$ définie par $u_0 = 7$ et $\forall n\in\N,\,u_{n+1} = 2 u_n^2$. Pour $n\in\N$, on note $q_n$ et $r_n$ le quotient et le reste de la division euclidienne de $u_n$ par $17$.

  1. Déterminer $r_6$.
  2. Déterminer le reste de la division euclidienne de $q_6$ par $17$.
  3. ★ Donner une expression explicite de $u_n$ en fonction de $n$.

    Indication : Conjecturer à partir des premières valeurs, ou se ramener à une suite $(v_n)$ vérifiant $v_{n+1} = v_n^2$.

1.4. Mesurer le temps d'exécution

La commande magique %time (ou timeit pour le shell en $\inv$) permet de mesurer le temps d'exécution. Dans l'exemple suivant, le calcul de $7^{2^{20}}$ prend 234 ms1.

In [1]: a = 2 ** 20
In [2]: %time b = 7 ** a
CPU times: user 224 ms, sys: 10.1 ms, total: 234 ms
Wall time: 234 ms
# Syntaxe correspondant à l'autre shell.
>>> timeit 7**(2**20)
0.23074946599808754 seconds on average

Comparer avec le temps nécessaire pour calculer $8^{2^{20}}$. ★ Comment expliquer la différence2 ?

Pour calculer $7^{2^{20}}$ Python n'effectue pas $2^{20}-1$ multiplications, mais seulement $20$ (avec de très grands nombres, ce qui explique le temps d'exécution). Comment3 ?

Si l'exécution ne termine pas, les icônes en haut du shell permettent de l'interrompre.

1.5. Le module math

Exécuter la commande import math pour importer le module math de Python. Ce module définit les fonctions mathématiques usuelles. Noter en particulier les fonctions math.sqrt (square root, pour racine carrée), math.log (logarithme), math.exp (exponentielle), math.floor (partie entière), ainsi que les constantes math.e et math.pi.

  • On peut trouver une liste des fonctions du module en exécutant help(math).
  • Vous pouvez obtenir la documentation d'une fonction en particulier en exécutant help(math.log). On peut y lire que cette fonction log peut prendre un deuxième argument facultatif donnant la base du logarithme. Par exemple log(2 ** 10, 2) renverra le logarithme en base $2$ de $2^{10}$, c'est-à-dire 10.0.
  • Exécuter from math import sqrt permet d'utiliser la fonction sqrt sans le préfixe math. Exécuter from math import * importe toutes les fonctions du module math.
  1. Comment récupérer le quotient de la division euclidienne de $a$ par $b$, sans utiliser les opérateurs // ou % ?
  2. Comparer les résultats des deux méthodes pour $a = 7^{32}$ et $b = 100$. Quel est le résultat correct ? Pouvez-vous expliquer ?

2. L'éditeur de texte

2.1. Définition d'une fonction

Dans l'éditeur de texte, recopier le code Python suivant. Il définit une fonction puiss_quatre qui prend un argument, noté x, et renvoie cet argument élevé à la puissance quatre, il définit également une variable e et calcule la puissance quatrième de $e$.

def puiss_quatre(x): # Définition d'une fonction nommée puiss_quatre
    b = x*x          # Affectation d'une variable intermédiaire
    return b*b       # La fonction renvoie b*b

e = 3                # Retour à l'indentation : en dehors de la fonction
print(puiss_quatre(e))

L'interpréteur Python ignore la fin des lignes à partir du symbole #. Cela permet d'annoter le code de commentaires, pour le lecteur.

Attention à la syntaxe. Pour définir une fonction :

  1. Utiliser le mot clef def, suivi du nom de la fonction, puis de ses arguments, entre parenthèses.
  2. Ne pas oublier les : à la fin de cette ligne.
  3. Indenter les instructions appartenant au corps de la fonction.

En Python l'indentation (l'espace au début de certaines lignes) est importante. Dans l'exemple plus haut, elle signale à l'interpréteur que ces instructions font partie du corps de la fonction. L'instruction e = 3 ne fait pas partie du corps de la fonction.

L'indentation est insérée automatiquement (par le shell également) quand vous appuyez sur la touche Entrée depuis la ligne précédente qui termine par :. Pour modifier l'indentation, utiliser les touches Tab (ajoute de l'indentation) et Shift + Tab (retire de l'indentation), depuis le début de la ligne.

2.2. Un éditeur interactif

Une fois le code précédent recopié (sans les commentaires), appuyer sur Ctrl+Entrée (ou Cmd+Entrée) pour faire exécuter le code dans le shell. Dans le shell, la variable e et la fonction puiss_quatre sont alors définies et le résultat de l'instruction puiss_quatre(2) est affiché. Il est maintenant possible d'exécuter dans le shell la commande puiss_quatre(e) pour obtenir $3^{4}=81$.

Bien qu'il soit possible de définir cette fonction directement dans le shell, l'éditeur permet

  • de sauvegarder votre code dans un fichier source .py
  • de modifier/corriger le code écrit avant de le réévaluer, ou de le copier-coller plus facilement
  1. Écrire une fonction fois_trois qui prend en argument un entier et renvoie un entier trois fois plus grand.
  2. Vérifier que votre fonction fonctionne en l'appelant depuis le shell, avec fois_trois(4) par exemple.
  3. Essayer la commande fois_trois("bonjour !"), expliquer.

Pour exécuter le fichier source, utiliser le raccourci Ctrl+Entrée. D'autres raccourcis sont décrits dans le menu Run.

Il est possible de séparer le fichier source en «cellules», délimitées par des lignes commençant par ### — chaque cellule correspondant à un exercice par exemple. Le raccourci Ctrl+Entrée n'exécute que la cellule actuelle.

En utilisant les fonctions math.floor (partie entière) et math.log10 (logarithme décimal), écrire une fonction qui prend en argument un entier $n\gt 0$ et qui renvoie le nombre de chiffres de l'écriture décimale de $n$. 4

3. Quelques notions de Python

3.1. L'affichage avec print

La fonction print permet d'afficher un message, ou la valeur d'une variable.

def puiss_quatre(x):
    print("On entre dans la fonction") # Les guillemets définissent une chaîne de caractères.
    b = x*x    # Une variable intermédiaire, qui vaut x²
    print("La variable b vaut", b)     # Les deux arguments seront affichés, séparés d'un espace
    return b*b # On a b² = (x²)² = x⁴

Après évaluation du code précédent,

In [1]: puiss_quatre(3)
On entre dans la fonction
La variable b vaut 9
Out[1]: 81

La fonction print prend un nombre arbitraire d'arguments (séparés par des virgules), qu'elle affiche, séparés d'un espace. À la fin, elle ajoute un retour à la ligne.

Quelles sont les valeurs affichées quand on évalue les extraits suivants ?

# Extrait 1
def f(a,b):
    z = 2*a+b
    return z
x = f(1,2)
y = f(2,1)
print(x,y)

# Extrait 2
def f(a,b):
    z = 2*a+b
    return z
x, y = 1, 1 # x=1 et y=1
x = f(x,y)
y = f(x,y)
print(x,y)
# Extrait 3
def f(a,b):
    return a*b
x = 1
y = 2
z = f(y, f(y, f(x,y)))
print(z)

  1. Écrire une fonction affiche_cinq_puiss qui prend en argument un entier n et affiche $5^n$, et ne renvoie rien.
  2. Écrire une fonction cinq_puiss qui prend en argument un entier n et qui renvoie $5^n$.
  3. Sans utiliser l'opérateur **, comment utiliser l'une de ces deux fonctions pour calculer $5^{(5^5)}$ ? Peut-on utiliser l'autre ?

3.2. Priorités opératoires

Les opérateurs de multiplications et divisions sont prioritaires sur l'addition et la soustraction.

On note $\phi = \frac{1+\sqrt{5}}{2}$ le nombre d'or. Comparer $e$ avec $\frac{4\phi +3\pi - 5}{4}$.

Les opérations de multiplication/division sont réalisées de gauche à droite.

In [1]: 3 * 2 // 3 # (3 * 2) // 3
Out[1]: 2

Laquelle des deux expressions $\left(a^b\right)^c$ et $a^{\left(b^c\right)}$ peut-on simplifier ?

Par convention, $a^{b^c} = a^{\left(b^c\right)}$.

Les opérations d'exponentiation sont réalisées de droite à gauche.

In [1]: 2 ** 3 ** 2
Out[1]: 512 # = 2⁹

3.3. Notion de couple

On peut représenter un couple de valeurs ou de variables en utilisant x, y ou (x,y).

In [1]: a = (3, 7) # définition d'un couple
In [2]: a[0] # Le premier élément correspond à
             # l'indice 0
Out[2]: 3
In [2]: a[1] # Le second à l'indice 1
Out[2]: 7
# À partir de a, on peut récupérer les deux
# valeurs par destructuration
In [3]: x, y = a # affectation de deux variables
In [4]: x
Out[4]: 3
In [5]: y
Out[5]: 7

L'affectation par couple peut être utilisée pour initialiser plusieurs variables en une seule ligne, ou échanger les valeurs de deux variables.

In [1]: x, y = 5, 7 # x = 5 et y = 7
In [2]: x, y
Out[2]: (5, 7)
In [3]: x, y = y, x # Échange des valeurs de x,y
In [4]: x, y
Out[4]: (7, 5)

Attention à la différence entre une fonction prenant en argument un couple est une fonction prenant en argument deux arguments.

def f(x,y): # Deux arguments
    return x+y
f(1,2)
def g(c): # c est un couple
    return c[0] + c[1]
g((1,2))

Représentation de nombres complexes

On représente un nombre complexe $z = x + iy$ par le couple $(x,y)$.

La fonction affiche_complexe ci-après affiche la représentation algébrique d'un nombre complexe en argument. On notera qu'elle ne renvoie rien.

def affiche_complexe(z):
    print(z[0], "+", z[1], "i")

def affiche_complexe(z):
    x, y = z
    print(x, "+", y, "i")
In [1]: affiche_complexe((3, 7))
3 + 7 i

  1. Écrire une fonction conjugue qui prend en argument un nombre complexe $z$ et renvoie $\ol{z}$.
  2. Écrire une fonction multiplication qui prend en argument deux nombres complexes $z_1$ et $z_2$ et renvoie leur produit $z_1z_2$.
  3. En utilisant les questions précédentes, écrire une fonction division qui prend en argument deux nombres complexes $z_1$ et $z_2$, avec $z_2\neq 0$ et qui renvoie le quotient $\frac{z_1}{z_2}$.
  4. Écrire une fonction puissance qui prend en argument un nombre complexe $z$ et un entier $n\in\N$ et renvoie $z^n$.
  5. Modifier cette dernière pour qu'elle marche pour tout $n\in\Z$ (si $z\neq 0$).
  1. Écrire une fonction module qui prend un nombre complexe z en argument et renvoie $|z|$.
  2. ★ Écrire une fonction argument qui renvoie un argument de z. Si z est nul, on renverra la valeur spéciale None.

    Indication : La fonction math.atan prend en argument un flottant $x$ et renvoie un flottant $\theta\in \interval]{-\frac{\pi}{2}, \frac{\pi}{2}}[$ tel que $\tan \theta = x$.

3.4. ★ Localité de variables

Par défaut,

  • toute variable définie à l'intérieur d'une fonction n'est pas accessible en dehors de la fonction. On dit que sa portée est locale.
  • les variables définies en dehors d'une fonction sont accessibles à l'intérieur de la fonction, mais ne peuvent pas être réaffectées depuis l'intérieur de la fonction.
def f(a,b):
    # z est une variable locale
    z = a * b
    return z
f(1,2)
print(z) # Erreur : z n'est pas défini

# x est une variable globale
x = 2
def f(a):
    return a+x
print(f(3)) # Affiche 5


x = 2 # variable globale
def f(a,b):
    # nouvelle variable locale
    # qui «cache» la globale
    x = 3
    return x
print(f(1,2), x) # Affiche 3, 2

Il est en fait possible de réaffecter une variable globale depuis l'intérieur d'une fonction, en la déclarant comme telle.

compteur = 0 # Compte le nb d'appels de f
def f():
    # On spécifie que le nom compteur utilise une portée globale
    global compteur
    compteur += 1
f(); f() # deux appels de f
print(compteur) # Affiche 2

3.5. ★ Mutabilité

Plutôt que de réaffecter une variable, certaines opérations peuvent modifier l'objet sous-jacent. Les types permettant ce genre d'opérations sont dits mutables. Les entiers et les flottants ne sont pas mutables, on ne peut que réaffecter des variables pointant vers une telle donnée. À l'intérieur d'une fonction, une telle réaffectation a une portée locale.

Les listes sont des objets mutables (contrairement aux chaînes de caractères). Une fonction peut donc modifier une liste qui lui est passée en argument.

x = 2
def f(a):
    a = a + 2 # Nouvelle affectation de la variable
              # locale a
f(x)
print(x) # Affiche 2, x n'a pas été modifiée
l = [1,2] # Une liste, un objet mutable
def f(li):
    li.append(3) # Modification de la liste li
    li[0] = 0
f(l)
print(l) # Affiche [0, 2, 3] : l a été modifiée

4. Exercices

  1. Écrire une fonction norme qui prend en argument trois flottants x,y,z et qui renvoie la norme du vecteur $\vvv{x}{y}{z}$.

  2. Écrire une nouvelle fonction norme_bis qui prenne plutôt en argument un triplet de flottants.
Essayez : normenormebis

Pour $a,b,c,d\in\R$, on considère les équations polynomiales $$(E_2) \colon ax^2 + bx + c = 0 \quad \et \quad (E_3)\colon ax^3 + bx^2 +c x + d = 0.$$

  1. En supposant que $(E_2)$ admette deux solutions réelles, écrire une fonction qui prend en argument $a,b$ et $c$, et les renvoie. Pour renvoyer deux valeurs x et y, on renvoie un couple : return x,y.
  2. Que se passe-t-il quand on appelle cette fonction avec les valeurs $a=1,b = -3$ et $c=2$ ?
  3. ★ Écrire une fonction qui prend en argument $a,b,c,d$ et renvoie True si et seulement si $(E_3)$ admet $3$ solutions distinctes.

  1. Écrire une fonction chiffre_des_unites qui prend en argument un entier naturel n et qui renvoie le chiffre des unités dans l'écriture décimale de $n$.
  2. Écrire une fonction chiffre_des_dizaines qui prend en argument un entier naturel n et qui renvoie le chiffre des dizaines dans l'écriture décimale de $n$.

On veut écrire une fonction premier_chiffre qui prend en argument un entier naturel $n$ et renvoie le premier chiffre de son écriture décimale. Par exemple, premier_chiffre(1024) renverra 1.

  1. Écrire une fonction premier_chiffre1 en utilisant les fonctions du module math.
  2. Écrire une fonction premier_chiffre2 en utilisant les fonctions str et int, qui permettent de faire des conversions de type. Par exemple, l'appel str(1024) renvoie "1024", l'appel int("1024") renvoie 1024. Si c est une chaîne de caractères, l'appel c[0] renvoie le premier caractère de cette chaîne.
  3. Écrire une fonction premier_chiffre3 en utilisant une boucle while et les opérateurs entiers.
  4. Discuter des avantages/inconvénients de chaque méthode.

Soit $N = 7^{15}!$ (factorielle de $7^{15}$).

  1. Déterminer le nombre de $0$ à la fin de l'écriture décimale de $N$, puis le dernier chiffre non nul.
  2. Quel est l'ordre de grandeur du nombre de chiffres décimaux de $N$ ?

Écrire une fonction alignés qui prend en argument trois points de $\R^2$ chacun représenté par un couple de flottants et renvoie le booléen True si les trois points sont sur une même droite, et False sinon.

On peut renvoyer un booléen en utilisant les opérateurs de comparaisons : return a == b, return a > b ou return a <= b.

Indication : Deux vecteurs $\vec u, \vec v$ sont colinéaires si et seulement si le déterminant $\begin{vmatrix}u_x & v_x \\ u_y & v_y\end{vmatrix}$ est nul.

Soient $A,B,C$ trois points du plan, d'affixes $z_A, z_B, z_C$.

  1. Quelle est l'aire du triangle ABC, en fonction des longueurs $AB$, $BC$ et de l'angle non orienté $\wh{ABC}$ ?

On dit que le triangle $ABC$ est orienté positivement si le point $C$ est à gauche de la demi-droite orientée $[AB)$, c'est-à-dire «si les points $A,B,C$ tournent dans le sens trigonométrique». Sinon, le triangle est orienté négativement. De manière équivalente, l'orientation est égale au signe de $\sin \theta$, où $\theta$ est l'angle orienté $\theta = (\oa{BC}, \oa{BA})$. On définit alors l'aire orientée de $ABC$ comme $\mc A_{ABC} = \sin \theta \lN\oa{BC}\rN \lN \oa{BA}\rN$.

  1. Justifier que $\mc A_{ABC} = \frac{1}{2}\Im \big((z_A - z_B) \ol{(z_C-z_B)}\big)$. En utilisant les fonctions de l'exercice No description for this link, écrire une fonction qui prend en argument les trois affixes $z_A, z_B, z_C$ et renvoie l'aire orientée.

    L'aire orientée est également donnée par le déterminant $\mc A_{ABC} = \frac{1}{2}\begin{vmatrix}x_C - x_B & x_A - x_B \\ y_C- y_B & y_A - y_B\end{vmatrix}$.

Notes de bas de page:

1

Wall time est le temps réel écoulé. Son nom fait référence à une horloge sur un mur.

2

En un certain sens, vous êtes capable de calculer $10^{100}$ plus rapidement qu'un ordinateur.

3

Pouvez-vous calculer $7^{(2^2)}$ à la main avec seulement deux multiplications ?

4

Indication : que renvoie l'appel math.log10(5876) ?